#include "ChestLock.h"
#include "Expand/PluginsManager.h"
#include "Expand/Plugins/AuthPlugin.h"

#include "Managers/BlocksManager.h"
#include "Expand/EventManager.h"
#include "Blocks/ChestBlock.h"
#include "Blocks/MagnetBlock.h"

#include "PlayerEvent.h"
#include "GameSingleton.h"
#include "Log.h"

#include <fstream>
#include <cfloat>

namespace CXHGT
{
    static const std::string titleText = "ChestLock";


    ChestLock::ChestLock() : lockBlockValue(MagnetBlock::Index())
    {
        m_playerEvent = new PlayerEvent(this);
        GameSingleton::eventManager->addEvent<IInventoryEvent>(m_playerEvent);
        GameSingleton::eventManager->addEvent<IInventoryOpenEvent>(m_playerEvent);
        GameSingleton::eventManager->addEvent<IPlayerEvent>(m_playerEvent);
    }

    const std::string &ChestLock::getPluginName()
    {
        static const std::string pluginName = "锁箱子";
        return pluginName;
    }

    const std::string &ChestLock::getIntroduce()
    {
        static const std::string introduce = "\n锁箱子";
        return introduce;
    }

    uint32_t ChestLock::getUseAuthLevel()
    {
        return 100;
    }

    AuthDisplayType ChestLock::getDisplayType()
    {
        return AuthDisplayType::Authority;
    }

    void ChestLock::processCmd(ChatObj &chatObj, std::vector<std::string> &cmdDataVec) {}


    bool ChestLock::getOwner(const Point3& point, GameGuid &outOwnerGuid)
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_ChestLockMap.find(point);
        if (it != m_ChestLockMap.end())
        {
            outOwnerGuid = it->second;
            return true;
        }
        return false;
    }

    bool ChestLock::addChestLock(const Point3& point, const GameGuid& userGuid)
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_ChestLockMap.find(point);
        if (it != m_ChestLockMap.end())
        {
            return false;
        }
        else
        {
            m_ChestLockMap[point] = userGuid;
        }
        return true;
    }

    bool ChestLock::breakChest(const Point3& point)
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_ChestLockMap.find(point);
        if (it != m_ChestLockMap.end())
        {
            m_ChestLockMap.erase(it);
            return true;
        }
        return false;
    }

    void ChestLock::load()
    {
        authPlugin = GameSingleton::pluginsManager->findPlugin<AuthPlugin>();


        Block *block = GameSingleton::blocksManager->blocks[ChestBlock::Index()];
        block->ProjectileResilience = 1.0f;         // 不会被击毁
        block->ExplosionResilience = FLT_MAX;       // 不会被炸毁
        block->IsFluidBlocker = true;               // 不会被流体冲掉
        block->FireDuration = 0.0f;                 // 不会着火

        std::ifstream stream;
        stream.open("./Plugins/ChestLock/ChestLock.json");
        if(stream.is_open())
        {
            nlohmann::json jsonData;
            stream >> jsonData;

            lockBlockValue = jsonData["lockBlockValue"].get<int32_t>();
            m_ChestLockMap = jsonData["data"].get<std::map<Point3, GameGuid>>();
        }
        stream.close();
    }

    void ChestLock::save()
    {
        const std::string pluginDataPath = "./Plugins/ChestLock";
        if(std::filesystem::exists(pluginDataPath) == false)
        {
            if(std::filesystem::create_directories(pluginDataPath) == false)
            {
                throw std::runtime_error("检测不到起床战争数据文件夹，并且无法创建新的 锁箱子 数据文件夹");
            }
        }

        m_mapMutex.lock();

        nlohmann::json jsonData = {
            { "lockBlockValue", lockBlockValue },
            { "data", m_ChestLockMap }};

        m_mapMutex.unlock();

        Utils::SaveTextFile(fmt::format("{}/ChestLock.json", pluginDataPath), jsonData.dump());
    }

    void ChestLock::getCmds(std::vector<std::string> &cmdVec){}

} // namespace PocketSurvival


using namespace PocketSurvival;

extern "C" void initialize()
{
    GameSingleton::pluginsManager->registerPlugin<CXHGT::ChestLock>();
    Log::Info("成功加载 ChestLock 插件");
}